package cc.eddic.practice.concurrency.impl;

import cc.eddic.practice.concurrency.LogItem;
import cc.eddic.practice.concurrency.LogItemParser;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;

@Slf4j
public class LogItemParserImpl implements LogItemParser {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z", Locale.ENGLISH);
    private static final Pattern LOG_PATTERN = Pattern.compile("(?<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+[\\w\\-]+\\s+[\\w\\-]+\\s+\\[" +
            "(?<dt>\\d+/\\w+/\\d+:\\d+:\\d+:\\d+\\s+\\+\\d+)]\\s+\"" + "(?<request>.*)\"\\s+" + "(?<status>\\d+)\\s+" +
            "(?<sent>\\d+)\\s+\"" + "(?<referer>[^\"]+)\"\\s+\"" + "(?<ua>[^\"]+)\"");
    private static final Pattern REQUEST_PATTERN = Pattern.compile("(?<method>\\w+)\\s+(?<url>[^ ]+)\\s+(?<protocol>[^ ]+)");

    @Override
    public Optional<LogItem> parse(String line) {
        val m = LOG_PATTERN.matcher(line);
        if (m.matches()) {
            String ip = m.group("ip");
            LocalDateTime ldt = LocalDateTime.parse(m.group("dt"), DATE_TIME_FORMATTER);
            String request = m.group("request");
            int status = Integer.parseInt(m.group("status"));
            long bytes = Long.parseLong(m.group("sent"));
            String referer = m.group("referer");
            String userAgent = m.group("ua");

            val m2 = REQUEST_PATTERN.matcher(request);
            String method = null;
            String protocol = null;
            String url;
            String path = null;
            Map<String, String> query = new HashMap<>();
            if (m2.matches()) {
                method = m2.group("method");
                protocol = m2.group("protocol");
                url = m2.group("url");

                if (url.contains("?")) {
                    int index = url.indexOf('?');
                    path = url.substring(0, index);
                } else {
                    path = url;
                }
            } else {
                return  Optional.of(new LogItem(ip, ldt, request, method, path, query, protocol, status, bytes, referer, userAgent));
            }

            LogItem logItem = new LogItem(ip, ldt, request, method, path, query, protocol, status, bytes, referer, userAgent);

            return Optional.of(logItem);

        } else {
            return Optional.empty();
        }
    }

}
